#include "stdafx.h"
#include "httpengine.h"

HttpEngine::HttpEngine()
:   QObject( NULL ),
    m_logged( false )
{
    // odniekadial ziska meno a heslo
    m_login = "martin";
    m_password = "mozi";

    m_manager = new QNetworkAccessManager( this );
    m_eventLoop.connect( m_manager, SIGNAL( finished( QNetworkReply* ) ), this, SLOT( replyFinished( QNetworkReply* ) ) );
}


HttpEngine::~HttpEngine()
{
}

HttpEngine & HttpEngine::httpEngine()
{
    static HttpEngine h;
    return h;
}

QString HttpEngine::errorStr() const
{
    return m_errorStr;
}

bool HttpEngine::processSessionStatus( SessionLoggedStatus::Enum sessionStatus, bool & logged )
{
     switch (sessionStatus)
     {
     case SessionLoggedStatus::NotLogged:
     case SessionLoggedStatus::Expired:
         m_sessionId.clear();
         logged = false;
         return true;

     case SessionLoggedStatus::Logged:
         logged = true;
         return true;

     case SessionLoggedStatus::BadLogin:
         m_errorStr = QObject::tr( "Invalid login" );
         logged = false;
         return false;

     default:
         assert( 0 );
         logged = false;
         return false;
     }
}

void HttpEngine::appendUrlData( QUrl & url, const QString & sqlQuery, QueryType queryType )
{
    if (m_sessionId.isEmpty())
        m_logged = false;
    else
        url.addQueryItem( "sessionId", m_sessionId );

    url.addQueryItem( "queryType", QString( "%1" ).arg( queryType ) );
    url.addQueryItem( "sqlQuery",  QString( sqlQuery.toUtf8().toBase64() ) );

    if (! m_logged)
    {
        url.addQueryItem( "login", m_login );
        url.addQueryItem( "password", m_password );
    }
}

bool HttpEngine::sendRequest( const QString & sqlQuery, QueryType queryType, QByteArray & resultData )
{
    m_finishStatus = HttpEngine::NotFinished;
    while (true)
    {
        QUrl url( "http://127.0.0.1/administratorremotedb.php" );
        appendUrlData( url, sqlQuery, queryType );
        QNetworkRequest request( url );
        request.setHeader( QNetworkRequest::ContentTypeHeader, "application/x-www-form-urlencoded" );
        QNetworkReply * reply = m_manager->post( request, url.encodedQuery() );
        if (waitForHttpCommunicationFinishes())
        {
            QByteArray xmlData = QByteArray::fromBase64( m_outData );
            if (! m_xmlDbParser.parse( xmlData ))
            {
                m_errorStr = QObject::tr( "Parse Http retrieved data error" );
                return false;
            }

            const ParseResult & parseResult = m_xmlDbParser.parseResult();
            if (! processSessionStatus( parseResult.sessionStatus, m_logged ))
                return false;

            m_sessionId = parseResult.sessionId;
            if (! m_logged)
                continue;

            if (! parseResult.queryErrorString.isEmpty())
            {
                m_errorStr = parseResult.queryErrorString;
                return false;
            }

            resultData = parseResult.queryResult;
            return true;
        }
        else
        {
            m_errorStr = QObject::tr( "Server not accesible" );
            return false;
        }
    }

    return false;
}

void HttpEngine::replyFinished( QNetworkReply * reply )
{   
    FinishStatus finishStatus = HttpEngine::NotFinished;
    m_outData.clear();

    // Reading attributes of the reply
    // e.g. the HTTP status code
    QVariant statusCodeV = reply->attribute( QNetworkRequest::HttpStatusCodeAttribute );
    // Or the target URL if it was a redirect:
    QVariant redirectionTargetUrl = reply->attribute( QNetworkRequest::RedirectionTargetAttribute );
    // see CS001432 on how to handle this
 
    QNetworkReply::NetworkError error = reply->error();
    if (error == QNetworkReply::NoError)
    {
        m_outData = reply->readAll();  // bytes
        finishStatus = HttpEngine::Suceed;
    }
    else
    {
        finishStatus = HttpEngine::Failed;
    }
 
    // We receive ownership of the reply object and therefore need to handle deletion.
    reply->deleteLater();
    m_finishStatus = finishStatus;
}

void HttpEngine::onTimeout()
{
    m_finishStatus = HttpEngine::TimeoutExpired;
}

bool HttpEngine::waitForHttpCommunicationFinishes()
{
    QTimer::singleShot( 5000, & m_eventLoop, SLOT( onTimeout() ) );

    while (1)
    {
        switch (m_finishStatus)
        {
        case NotFinished:
            break;

        case Suceed:
            return true;

        case TimeoutExpired:
        case Failed:
            return false;

        default:
            assert( 0 );
            return false;
        }

        m_eventLoop.processEvents( );
    }

    return false;
}